Skip to content

feat(agent): client helper + cache cloud-init install (FJB-94 Phase C)#113

Open
hstern wants to merge 1 commit into
mainfrom
feat/fjb-94-agent-dialer-and-cache
Open

feat(agent): client helper + cache cloud-init install (FJB-94 Phase C)#113
hstern wants to merge 1 commit into
mainfrom
feat/fjb-94-agent-dialer-and-cache

Conversation

@hstern

@hstern hstern commented May 29, 2026

Copy link
Copy Markdown
Owner

Summary

Third (final) slice of FJB-94. Lands the orchestrator-side dial + cache deploy. Together with Phases A/B, the agent foundation is complete: agent installed on workers + cache, orchestrator has the wire shape to dial both.

Builds on: PR #111 (Phase B). PR diff shows Phase B's commits too until Phase B merges to main, at which point this rebases clean and the diff narrows to Phase C only.

What's in

  • internal/agent/client.goNewClient(ClientOptions{Addr, Token, DialContext}) returning an AgentServiceClient. h2c via http2.Transport.AllowHTTP + DialTLSContext. Bearer interceptor wraps unary AND streaming RPCs (FJB-93's Exec is bidi).
  • Cache deploycacheCloudInitParams gains the agent triplet; bootstrap.FJBAgentServiceUnit() is the canonical unit shared with worker installs. Linode.SetFJBAgent is the duck-typed wiring main.go uses.
  • internal/provider/linode/cache-cloud-init.yaml.tmpl — same install block as workers, gated on FJBAgentDownloadURL.
  • cmd/fj-bellows/main.gobuildOrchestratorConfig pushes the knobs into the provider via duck-typed SetFJBAgent so the managed cache renders the same install.

Test plan

  • 5 new agent.NewClient cases over h2c.
  • 3 new cache renderer cases (no-artifacts when disabled, full render when enabled, token required).
  • go test -race ./... clean.
  • golangci-lint clean.

🤖 Generated with Claude Code

@hstern hstern enabled auto-merge (squash) May 29, 2026 00:39
Third slice of FJB-94. Lands the orchestrator-side dial — generic
agent.NewClient producing an AgentServiceClient given a DialContext,
addr, and bearer token — plus the cache cloud-init extension that
installs fjbagent on the cache nanode the same way Phase B installed
it on workers. Together with Phase A/B, this completes the FJB-94
foundation.

agent.NewClient:
  - DialContextFunc abstraction lets the orchestrator pass
    wg.Tunnel.DialContext in production, net.Dialer.DialContext in
    tests.
  - HTTP/2 cleartext via http2.Transport.AllowHTTP + DialTLSContext
    returning a plain TCP conn. Matches agent server-side h2c.
  - Bearer interceptor sets Authorization on both unary and
    streaming RPCs (FJB-93's Exec needs the streaming path).

Cache deploy:
  - cacheCloudInitParams gains FJBAgentDownloadURL + FJBAgentToken +
    FJBAgentServiceUnit + FJBAgentListenPort; ServiceUnit comes from
    bootstrap.FJBAgentServiceUnit() so worker and cache share one
    systemd unit file.
  - cache-cloud-init.yaml.tmpl mirrors the worker install block:
    same fjb system user, same auth.token mode 0600, same
    /etc/default/fjbagent env file, same systemd Type=notify unit,
    same curl-then-enable-service runcmd. Gated on
    FJBAgentDownloadURL non-empty.
  - Linode.SetFJBAgent is the duck-typed wiring main.go uses
    (matching SetTransportMode / SetACLSource shape); empty pair
    disables the install for the cache the same way it does for
    workers.

main.go:
  - buildOrchestratorConfig pushes the resolved knobs into the
    provider via duck typing inline (skip the docker provider, no-op
    when cache isn't configured). Locality > separate helper here
    since the call site is small.

Tests: 5 new agent.NewClient cases over h2c (Health no-auth + with
token + wrong-token rejected, Exec streaming with bearer, sentinel
DialContext is actually used), 3 new cache renderer cases. Full
go test -race ./... clean. golangci-lint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hstern hstern force-pushed the feat/fjb-94-agent-dialer-and-cache branch from 14f41b9 to 8c4c79b Compare May 29, 2026 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant